#ifndef _LOG_HELPER_HPP
#define _LOG_HELPER_HPP

#include <stdint.h>
#include <sstream>
#include <iostream>

namespace RockLog
{
    //#define Use_OutputDebugString
    #ifdef Use_OutputDebugString
        #include <windows.h>
    #elif defined(Use_QDebug)
        #include <QDebug>
    #endif


    enum LogLevel
    {
        kDisable    = -1,
        kDebug        = 0,
        kInfo        = 1,
        kWarn        = 2,
        kErr        = 3,
    };

    class LogHelper
    {
    public:
        LogHelper() 
        {
            _level = (int32_t)kDebug;
        }

        LogHelper(int32_t level, const char* func, uint32_t line)
            :_level(level), _funcName(func), _lineNo(line)
        {
        }

        inline LogHelper& operator<<(std::ostream& (*log)(std::ostream&))
        {
            _ss << log;
            return *this;
        }

        template <typename T>
        inline LogHelper& operator<<(const T& log) {
            if (_ss.str().length() > 0){
                _ss << " ";
            }
            _ss << log;
            return *this;
        }

        ~LogHelper()
        {
            std::ostringstream oss;
            switch (_level)
            {
            case (int32_t)kDebug:
                oss << "[I] -";
                break;
            case (int32_t)kInfo:
                oss << "[D] -";
                break;
            case (int32_t)kWarn:
                oss << "[W] -";
                break;
            case (int32_t)kErr:
                oss << "[E] -";
                break;
            case (int32_t)kDisable:
                return;
            default:
                break;
            }

            oss << "[" << _funcName << ":" << _lineNo << "] - ";
            oss << _ss.str();
    #ifdef Use_OutputDebugString
            oss << std::endl;
            OutputDebugStringA(oss.str().c_str());
    #elif defined (Use_QDebug)
            qDebug() << oss.str().c_str();
    #else
            std::cout << oss.str() << std::endl;
    #endif

        }
    private:
        int32_t                _level;
        std::stringstream    _ss; 
        std::string            _funcName;
        uint32_t            _lineNo;
    };

    #define LOG(X)        LogHelper(X, __FUNCTION__, __LINE__)
};


#endif
